Set up libraries

Load data

c14dates <- read_csv("c14dates.csv")
Rows: 1452 Columns: 16── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (10): industry, site, unit, calib.curve, sample.id, material, delta 13, method&id, comments, citation
dbl  (6): ID, Use, BP.cal.median, C14.mean, C14.SD, C14.COV
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Figure 1: Journal Publications

rr.papers %>% 
  ggplot(aes(x=years)) + 
  geom_path(aes(y=JAS.risk/JAS.papers, color='Journal of Archaeological Science', lty='risk'), group=1, lwd=1.5) + 
  geom_path(aes(y=JAS.resilience/JAS.papers, color='Journal of Archaeological Science', lty='resilience'), group=1, lwd=1.5) + 
  geom_path(aes(y=Antiquity.risk/Antiquity.papers, color='Antiquity', lty='risk'), group=1, lwd=1.5) + 
  geom_path(aes(y=Antiquity.resilience/Antiquity.papers, color='Antiquity', lty='resilience'), group=1, lwd=1.5) + 
  scale_y_continuous(labels = scales::percent) + 
  scale_color_manual(values = c('Journal of Archaeological Science' = 'red', 'Antiquity' = 'blue')) + 
  scale_linetype_manual(values = c('risk' = 'solid', 'resilience' = 'dashed')) + 
  labs(title = "Papers Mentioning Risk or Resilience", 
       subtitle = "Change in Past 40 Years", 
       x="5-year intervals", 
       y="% of papers published", 
       color='journal:', 
       linetype='topic:') + 
  theme_bw(base_size = 30) + 
  theme(legend.position = 'bottom', legend.key.width =  unit(50, "points"))

Modeling Biocultural Interaction

Figure 2: NGRIP2 and GISP2 entire cores

icecores %>%
  ggplot() + 
  geom_point(aes(x=years.BP, y=d18O.NGRIP2.ppt), color='blue', size=.5, alpha=.2) + 
  geom_point(aes(x=years.BP, y=d18O.GISP2.ppt), color='pink2', size=.5, alpha=.2) + 
  geom_smooth(aes(x=years.BP, y=d18O.NGRIP2.ppt, color='ngrip2', lty='ngrip2'), method='loess', span=.01, se=FALSE, lwd = 1)  + 
  geom_smooth(aes(x=years.BP, y=d18O.GISP2.ppt, color='gisp2', lty='gisp2'), method='loess', span=.01, se=FALSE, lwd = 1) + 
  scale_colour_manual(name=NULL, values =c('gisp2'='indianred3','ngrip2'='navy'), labels = c('GISP2','NGRIP2')) + 
  scale_linetype_manual(name=NULL, values =c('gisp2'='solid','ngrip2'='solid'), labels = c('GISP2','NGRIP2')) + 
  scale_x_reverse() + 
  #scale_x_continuous(breaks=c(19000,14000,10000), labels = c("19000","14000","10000"), trans = "reverse") + 
  geom_vline(xintercept = c(27000,22000,11000), lty='dashed', lwd=1) + 
  labs(x="years cal BP", 
       y="delta O18\ncolder << — >> warmer", 
       color="Cores",
       title="Paleoclimate Proxies from Greenland Ice Cores") +
  theme_minimal(base_size = 18) + 
  theme(legend.position="bottom", 
        plot.title = element_text(face = "bold", hjust = 0.5), 
        )

Figure 3: Box Plots with Condensed Fitness Categories

Hominin_demography %>% 
  mutate(fitness.aggregated = Fitness, 
         fitness.aggregated = recode(fitness.aggregated, 
                                     "birthrate=deathrate"="equal fitness", 
                                     "birthrate>deathrate"="equal fitness", 
                                     "MM higher mortality"="MM less fit", 
                                     "MM lower fertility"="MM less fit", 
                                     "MM lower mortality"="MM more fit", 
                                     "MN higher mortality"="MN less fit", 
                                     "MN lower fertility"="MN less fit", 
                                     "MN lower mortality"="MN more fit", 
                                     "NN higher mortality"="NN less fit", 
                                     "NN lower fertility"="NN less fit", 
                                     "NN lower mortality"="NN more fit"),
         fitness.aggregated = factor(fitness.aggregated, 
                                     levels = c(
                                       "equal fitness", 
                                       "MM less fit", 
                                       "MM more fit", 
                                       "MN less fit", 
                                       "MN more fit", 
                                       "NN less fit", 
                                       "NN more fit"))) %>% 
  ggplot(aes(x=phenotype, y=population)) + 
  geom_boxplot(fill="grey") + 
  facet_grid(fitness.aggregated~factor(home.range.radius), scales="free_y") + 
  labs(x="agent phenotype", y="population at end of simulation") + 
  theme_bw(base_size = 16)

Figure 4: Example Model Trajectory with Logistical Foraging (Foraging Radius=12)

Hominin_demography_trajectory %>% 
  ggplot(aes(y=population, x=step)) + 
  geom_line(aes(color=phenotype), size=2) +
  scale_color_manual(values = c("red", "orange", "grey", "forestgreen", "blue")) + 
  labs(x="model step", y="population", color="agent phenotype") + 
  theme_bw(base_size = 16) + 
  theme(legend.position="bottom")

Demographic Dynamics of West Mediterranean

Figure 5a: Summed Probability Distribution (SPD) of Radiocarbon Dates in the West Mediterranean

Calibrate dates

c14dates$BP.cal.median <- c14dates %>% 
  with(., calibrate(x=C14.mean, errors=C14.SD, calCurves = calib.curve, normalised=TRUE, calMatrix=FALSE)) %>% 
  medCal()

Calculate SPD for entire region

Dates file filtered to remove all date with COV > 0.1

Graph SPD

par(mar=c(7,10,7,3))
plot(model.all, xlim = c(35000,8000), col.obs = 'red', lwd.obs = 3, drawaxes = F)
axis(1, cex.axis = 1, pos = -.0006)
axis(2, cex.axis = 1, pos = 35500)
mtext(side=1, line=3, "years cal BP", cex=1.3)
mtext(side=2, line=4, "summed probability", cex=1.3)
title(main=paste("West Mediterranean Late Pleistocene Assemblages (N = ", nrow(subset(c14dates, calib.curve != "normal")), ")"), cex.main = 1.5)

Figure 5b: SPD Permutation Test of Aggregated Technocomplexes

Classify aggregated technocomplexes

c14dates <- c14dates %>% 
  mutate(industry.group = 
           case_when(
             str_detect(tolower(industry), "aurig") ~ "Aurignacian", 
             str_detect(tolower(industry), "gdrav") ~ "Gravettian",  
             str_detect(tolower(industry), "solut") ~ "Solutrean",
             str_detect(tolower(industry), "middle solutrean") ~ "Solutrean", 
             str_detect(tolower(industry), "salp") ~ "Solutrean",              
             str_detect(tolower(industry), "epig") ~ "Magdalenian",  
             str_detect(tolower(industry), "epi-gr") ~ "Magdalenian",
             str_detect(tolower(industry), "eppig") ~ "Magdalenian",
             str_detect(tolower(industry), "eppgr") ~ "Magdalenian",
             str_detect(tolower(industry), "apig") ~ "Magdalenian",
             str_detect(tolower(industry), "magd") ~ "Magdalenian",
             str_detect(tolower(industry), "badeg") ~ "Magdalenian",
             str_detect(tolower(industry), "gravet") ~ "Gravettian",  
             str_detect(tolower(industry), "gravt") ~ "Gravettian",  
             str_detect(tolower(industry), "azil") ~ "Epipaleolithic", 
             str_detect(tolower(industry), "romanell") ~ "Epipaleolithic", 
             str_detect(tolower(industry), "epipal") ~ "Epipaleolithic", 
             str_detect(tolower(industry), "mesol") ~ "Mesolithic", 
             str_detect(tolower(industry), "sauve") ~ "Mesolithic", 
             str_detect(tolower(industry), "tarden") ~ "Mesolithic", 
             str_detect(tolower(industry), "montcl") ~ "Mesolithic", 
             str_detect(tolower(industry), "montad") ~ "Mesolithic", 
             str_detect(tolower(industry), "castel") ~ "Mesolithic"
             ), 
         industry.group = factor(industry.group, 
                                 levels = c("Aurignacian", 
                                            "Gravettian", 
                                            "Solutrean", 
                                            "Magdalenian", 
                                            "Epipaleolithic", 
                                            "Mesolithic")),
         .after=industry)

Permutation test of aggregated technocomplexes

Permutation test results

summary(perm.test)
'permTest()' function summary:

Number of sets: 6
Statistical Significance computed using 200 simulations. 

--- Aurignacian ---
Number of radiocarbon dates:94
Number of bins:84

Global p-value: 0.00498

Significant positive local deviations at:
40000~29265 BP 
28924~28146 BP 
27436~26419 BP 

Significant negative local deviations at:
18435~12504 BP 
12048~11097 BP 
10230~7646 BP 

--- Gravettian ---
Number of radiocarbon dates:131
Number of bins:109

Global p-value: 0.00498

Significant positive local deviations at:
32846~25171 BP 
24609~24371 BP 
24318~24295 BP 
24181~24163 BP 

Significant negative local deviations at:
21508~21288 BP 
20184~19623 BP 
16356~13859 BP 
13809~10550 BP 
9793~7266 BP 

--- Solutrean ---
Number of radiocarbon dates:120
Number of bins:88

Global p-value: 0.00498

Significant positive local deviations at:
26079~19630 BP 

Significant negative local deviations at:
31656~31025 BP 
18570~18569 BP 
18560~18229 BP 
18121~18117 BP 
13728~12489 BP 
12168~7419 BP 

--- Magdalenian ---
Number of radiocarbon dates:516
Number of bins:350

Global p-value: 0.00498

Significant positive local deviations at:
20402~20034 BP 
19782~12264 BP 

Significant negative local deviations at:
36464~24702 BP 
24446~23560 BP 
23394~23225 BP 
23221~22834 BP 
11441~10975 BP 
10860~7250 BP 

--- Epipaleolithic ---
Number of radiocarbon dates:120
Number of bins:94

Global p-value: 0.00498

Significant positive local deviations at:
13305~10489 BP 
10483~10341 BP 
10146~9669 BP 

Significant negative local deviations at:
32202~26954 BP 
26507~25629 BP 
25500~22554 BP 
20524~19706 BP 
18871~17393 BP 
16130~14915 BP 

--- Mesolithic ---
Number of radiocarbon dates:312
Number of bins:206

Global p-value: 0.00498

Significant positive local deviations at:
11324~7000 BP 

Significant negative local deviations at:
34855~11918 BP 

Graph Permutations

plot(perm.test, 
     focalm = "Aurignacian", 
     xlim = c(35000,8000), 
     col.obs = 'red', 
     lwd.obs = 3,
     bbty = 'b', 
     ylim = c(0, 0.04),
     drawaxes = F)
  axis(1, cex.axis = 1, pos = -.0006)
  axis(2, cex.axis = 1, pos = 35500)
  mtext(side=1, line=3, "years cal BP", cex=1.3)
  mtext(side=2, line=4, "summed probability", cex=1.3)
  title(main=paste("Aurignacian (N = ", nrow(subset(c14dates, industry.group == "Aurignacian")), ")"), cex.main = 1.5)

 
plot(perm.test, 
     focalm = "Gravettian", 
     xlim = c(35000,8000), 
     col.obs = 'red', 
     lwd.obs = 3,
     bbty = 'b', 
     ylim = c(0, 0.04),
     drawaxes = F)
  axis(1, cex.axis = 1, pos = -.0006)
  axis(2, cex.axis = 1, pos = 35500)
  mtext(side=1, line=3, "years cal BP", cex=1.3)
  mtext(side=2, line=4, "summed probability", cex=1.3)
  title(main=paste("Gravettian (N = ", nrow(subset(c14dates, industry.group == "Gravettian")), ")"), cex.main = 1.5)

  
plot(perm.test, 
     focalm = "Solutrean", 
     xlim = c(35000,8000), 
     col.obs = 'red', 
     lwd.obs = 3,
     bbty = 'b', 
     ylim = c(0, 0.04),
     drawaxes = F)
  axis(1, cex.axis = 1, pos = -.0006)
  axis(2, cex.axis = 1, pos = 35500)
  mtext(side=1, line=3, "years cal BP", cex=1.3)
  mtext(side=2, line=4, "summed probability", cex=1.3)
  title(main=paste("Solutrean (N = ", nrow(subset(c14dates, industry.group == "Solutrean")), ")"), cex.main = 1.5)

  
plot(perm.test, 
     focalm = "Magdalenian", 
     xlim = c(35000,8000), 
     col.obs = 'red', 
     lwd.obs = 3,
     bbty = 'b', 
     ylim = c(0, 0.1),
     drawaxes = F)
  axis(1, cex.axis = 1, pos = -.0006)
  axis(2, cex.axis = 1, pos = 35500)
  mtext(side=1, line=3, "years cal BP", cex=1.3)
  mtext(side=2, line=4, "summed probability", cex=1.3)
  title(main=paste("Magdalenian (N = ", nrow(subset(c14dates, industry.group == "Magdalenian")), ")"), cex.main = 1.5)

  
plot(perm.test, 
     focalm = "Epipaleolithic", 
     xlim = c(35000,8000), 
     col.obs = 'red', 
     lwd.obs = 3,
     bbty = 'b', 
     ylim = c(0, 0.04),
     drawaxes = F)
  axis(1, cex.axis = 1, pos = -.0006)
  axis(2, cex.axis = 1, pos = 35500)
  mtext(side=1, line=3, "years cal BP", cex=1.3)
  mtext(side=2, line=4, "summed probability", cex=1.3)
  title(main=paste("Epipaleolithic (N = ", nrow(subset(c14dates, industry.group == "Epipaleolithic")), ")"), cex.main = 1.5)

  
plot(perm.test, 
     focalm = "Mesolithic", 
     xlim = c(35000,8000), 
     col.obs = 'red', 
     lwd.obs = 3,
     bbty = 'b', 
     ylim = c(0, 0.12), 
     drawaxes = F)
  axis(1, cex.axis = 1, pos = -.0006)
  axis(2, cex.axis = 1, pos = 35500)
  mtext(side=1, line=3, "years cal BP", cex=1.3)
  mtext(side=2, line=4, "summed probability", cex=1.3)
  title(main=paste("Mesolithic (N = ", nrow(subset(c14dates, industry.group == "Mesolithic")), ")"), cex.main = 1.5)

LS0tCnRpdGxlOiAiUmlzayBhbmQgUmVzaWxpZW5jZSBpbiBEZWVwIFRpbWUiCnN1YnRpdGxlOiAiQW5hbHlzaXMgU2NyaXB0cyBmb3IgUGFwZXIgUHVibGlzaGVkIGluIF9Ib2xvY2VuZV8iCmF1dGhvcjogIkMgTWljaGFlbCBCYXJ0b24sIEFyaXpvbmEgU3RhdGUgVW5pdmVyc2l0eSIKZGF0ZTogIjIwMjMtMDMtMjciCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KClNldCB1cCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0UsIGVjaG89VH0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShyY2FyYm9uKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShwYXJhbGxlbCkKCm5jb3JlcyA8LSBkZXRlY3RDb3JlcygpCm9wdGlvbnMoTmNwdXMgPSBuY29yZXMpCmBgYAoKCkxvYWQgZGF0YQpgYGB7ciBsb2FkIGRhdGEsIGVjaG89VH0KYzE0ZGF0ZXMgPC0gcmVhZF9jc3YoImMxNGRhdGVzLmNzdiIpCgpIb21pbmluX2RlbW9ncmFwaHkgPC0gcmVhZF9jc3YoIkhvbWluaW5fZGVtb2dyYXBoeS5jc3YiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9IGNvbHMoLi4uMSA9IGNvbF9pbnRlZ2VyKCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob21lLnJhbmdlLnJhZGl1cyA9IGNvbF9pbnRlZ2VyKCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3B1bGF0aW9uID0gY29sX2ludGVnZXIoKSkpCkhvbWluaW5fZGVtb2dyYXBoeSA8LSBIb21pbmluX2RlbW9ncmFwaHkgJT4lIAogIG11dGF0ZShwaGVub3R5cGUgPSByZWNvZGUocGhlbm90eXBlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxIE1NIj0iTU0iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyIE0tdHlwZSI9Ik0tdHlwZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIjMgaHlicmlkIj0iTU4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICI0IE4tdHlwZSI9Ik4tdHlwZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIjUgTk4iPSJOTiIpLCAKICAgICAgICAgRml0bmVzcyA9IHJlY29kZShGaXRuZXNzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAiaHlicmlkIGhpZ2hlciBtb3J0YWxpdHkiPSJNTiBoaWdoZXIgbW9ydGFsaXR5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgImh5YnJpZCBsb3dlciBmZXJ0aWxpdHkiPSJNTiBsb3dlciBmZXJ0aWxpdHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAiaHlicmlkIGxvd2VyIG1vcnRhbGl0eSI9Ik1OIGxvd2VyIG1vcnRhbGl0eSIpKSAlPiUgCiAgbXV0YXRlKHBoZW5vdHlwZSA9IGZhY3RvcihwaGVub3R5cGUsIGxldmVscyA9IGMoIk1NIiwgIk0tdHlwZSIsICJNTiIsICJOLXR5cGUiLCAiTk4iKSkpCgpIb21pbmluX2RlbW9ncmFwaHlfdHJhamVjdG9yeSA8LSByZWFkX2NzdigiSG9taW5pbl9kZW1vZ3JhcGh5X3RyYWplY3Rvcmllcy5jc3YiKQpIb21pbmluX2RlbW9ncmFwaHlfdHJhamVjdG9yeSA8LSBIb21pbmluX2RlbW9ncmFwaHlfdHJhamVjdG9yeSAlPiUgCiAgc2VsZWN0KE0udHlwZS54LCBlbmRzX3dpdGgoIi55IikpICU+JSAKICByZW5hbWUoc3RlcCA9IE0udHlwZS54LCAKICAgICAgICAgIk0tVHlwZSIgPSBNLnR5cGUueSwgCiAgICAgICAgICJOLVR5cGUiID0gTi50eXBlLnksIAogICAgICAgICBNTiA9IGh5YnJpZC55LAogICAgICAgICBNTSA9IE1NLnksIAogICAgICAgICBOTiA9IE5OLnkpICU+JSAKICBwaXZvdF9sb25nZXIoMjo2LCBuYW1lc190byA9ICJwaGVub3R5cGUiLCB2YWx1ZXNfdG8gPSAicG9wdWxhdGlvbiIpICU+JSAKICBtdXRhdGUocGhlbm90eXBlID0gZmFjdG9yKHBoZW5vdHlwZSwgbGV2ZWxzID0gYygiTU0iLCAiTS1UeXBlIiwgIk1OIiwgIk4tVHlwZSIsICJOTiIpKSkKCmljZWNvcmVzIDwtIHJlYWRfY3N2KCJpY2Vjb3Jlcy5jc3YiKQoKcnIucGFwZXJzIDwtIHJlYWRfY3N2KCJycl9wYXBlcnMuY3N2IikKCmBgYAoKIyMjIEZpZ3VyZSAxOiBKb3VybmFsIFB1YmxpY2F0aW9ucwoKYGBge3IgYmlibGlvbWV0cmljcywgZWNobz1ULCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NX0KcnIucGFwZXJzICU+JSAKICBnZ3Bsb3QoYWVzKHg9eWVhcnMpKSArIAogIGdlb21fcGF0aChhZXMoeT1KQVMucmlzay9KQVMucGFwZXJzLCBjb2xvcj0nSm91cm5hbCBvZiBBcmNoYWVvbG9naWNhbCBTY2llbmNlJywgbHR5PSdyaXNrJyksIGdyb3VwPTEsIGx3ZD0xLjUpICsgCiAgZ2VvbV9wYXRoKGFlcyh5PUpBUy5yZXNpbGllbmNlL0pBUy5wYXBlcnMsIGNvbG9yPSdKb3VybmFsIG9mIEFyY2hhZW9sb2dpY2FsIFNjaWVuY2UnLCBsdHk9J3Jlc2lsaWVuY2UnKSwgZ3JvdXA9MSwgbHdkPTEuNSkgKyAKICBnZW9tX3BhdGgoYWVzKHk9QW50aXF1aXR5LnJpc2svQW50aXF1aXR5LnBhcGVycywgY29sb3I9J0FudGlxdWl0eScsIGx0eT0ncmlzaycpLCBncm91cD0xLCBsd2Q9MS41KSArIAogIGdlb21fcGF0aChhZXMoeT1BbnRpcXVpdHkucmVzaWxpZW5jZS9BbnRpcXVpdHkucGFwZXJzLCBjb2xvcj0nQW50aXF1aXR5JywgbHR5PSdyZXNpbGllbmNlJyksIGdyb3VwPTEsIGx3ZD0xLjUpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygnSm91cm5hbCBvZiBBcmNoYWVvbG9naWNhbCBTY2llbmNlJyA9ICdyZWQnLCAnQW50aXF1aXR5JyA9ICdibHVlJykpICsgCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoJ3Jpc2snID0gJ3NvbGlkJywgJ3Jlc2lsaWVuY2UnID0gJ2Rhc2hlZCcpKSArIAogIGxhYnModGl0bGUgPSAiUGFwZXJzIE1lbnRpb25pbmcgUmlzayBvciBSZXNpbGllbmNlIiwgCiAgICAgICBzdWJ0aXRsZSA9ICJDaGFuZ2UgaW4gUGFzdCA0MCBZZWFycyIsIAogICAgICAgeD0iNS15ZWFyIGludGVydmFscyIsIAogICAgICAgeT0iJSBvZiBwYXBlcnMgcHVibGlzaGVkIiwgCiAgICAgICBjb2xvcj0nam91cm5hbDonLCAKICAgICAgIGxpbmV0eXBlPSd0b3BpYzonKSArIAogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDMwKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nLCBsZWdlbmQua2V5LndpZHRoID0gIHVuaXQoNTAsICJwb2ludHMiKSkKYGBgCgoKIyMgTW9kZWxpbmcgQmlvY3VsdHVyYWwgSW50ZXJhY3Rpb24KCiMjIyBGaWd1cmUgMjogTkdSSVAyIGFuZCBHSVNQMiBlbnRpcmUgY29yZXMKCmBgYHtyIE5HUklQMiZHSVNQMiwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTZ9CmljZWNvcmVzICU+JQogIGdncGxvdCgpICsgCiAgZ2VvbV9wb2ludChhZXMoeD15ZWFycy5CUCwgeT1kMThPLk5HUklQMi5wcHQpLCBjb2xvcj0nYmx1ZScsIHNpemU9LjUsIGFscGhhPS4yKSArIAogIGdlb21fcG9pbnQoYWVzKHg9eWVhcnMuQlAsIHk9ZDE4Ty5HSVNQMi5wcHQpLCBjb2xvcj0ncGluazInLCBzaXplPS41LCBhbHBoYT0uMikgKyAKICBnZW9tX3Ntb290aChhZXMoeD15ZWFycy5CUCwgeT1kMThPLk5HUklQMi5wcHQsIGNvbG9yPSduZ3JpcDInLCBsdHk9J25ncmlwMicpLCBtZXRob2Q9J2xvZXNzJywgc3Bhbj0uMDEsIHNlPUZBTFNFLCBsd2QgPSAxKSAgKyAKICBnZW9tX3Ntb290aChhZXMoeD15ZWFycy5CUCwgeT1kMThPLkdJU1AyLnBwdCwgY29sb3I9J2dpc3AyJywgbHR5PSdnaXNwMicpLCBtZXRob2Q9J2xvZXNzJywgc3Bhbj0uMDEsIHNlPUZBTFNFLCBsd2QgPSAxKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwobmFtZT1OVUxMLCB2YWx1ZXMgPWMoJ2dpc3AyJz0naW5kaWFucmVkMycsJ25ncmlwMic9J25hdnknKSwgbGFiZWxzID0gYygnR0lTUDInLCdOR1JJUDInKSkgKyAKICBzY2FsZV9saW5ldHlwZV9tYW51YWwobmFtZT1OVUxMLCB2YWx1ZXMgPWMoJ2dpc3AyJz0nc29saWQnLCduZ3JpcDInPSdzb2xpZCcpLCBsYWJlbHMgPSBjKCdHSVNQMicsJ05HUklQMicpKSArIAogIHNjYWxlX3hfcmV2ZXJzZSgpICsgCiAgI3NjYWxlX3hfY29udGludW91cyhicmVha3M9YygxOTAwMCwxNDAwMCwxMDAwMCksIGxhYmVscyA9IGMoIjE5MDAwIiwiMTQwMDAiLCIxMDAwMCIpLCB0cmFucyA9ICJyZXZlcnNlIikgKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKDI3MDAwLDIyMDAwLDExMDAwKSwgbHR5PSdkYXNoZWQnLCBsd2Q9MSkgKyAKICBsYWJzKHg9InllYXJzIGNhbCBCUCIsIAogICAgICAgeT0iZGVsdGEgTzE4XG5jb2xkZXIgPDwg4oCUID4+IHdhcm1lciIsIAogICAgICAgY29sb3I9IkNvcmVzIiwKICAgICAgIHRpdGxlPSJQYWxlb2NsaW1hdGUgUHJveGllcyBmcm9tIEdyZWVubGFuZCBJY2UgQ29yZXMiKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxOCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIsIAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjUpLCAKICAgICAgICApCmBgYAoKIyMjIEZpZ3VyZSAzOiBCb3ggUGxvdHMgd2l0aCBDb25kZW5zZWQgRml0bmVzcyBDYXRlZ29yaWVzCgpgYGB7ciBlY2hvPVQsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0xMn0KSG9taW5pbl9kZW1vZ3JhcGh5ICU+JSAKICBtdXRhdGUoZml0bmVzcy5hZ2dyZWdhdGVkID0gRml0bmVzcywgCiAgICAgICAgIGZpdG5lc3MuYWdncmVnYXRlZCA9IHJlY29kZShmaXRuZXNzLmFnZ3JlZ2F0ZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJpcnRocmF0ZT1kZWF0aHJhdGUiPSJlcXVhbCBmaXRuZXNzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYmlydGhyYXRlPmRlYXRocmF0ZSI9ImVxdWFsIGZpdG5lc3MiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNTSBoaWdoZXIgbW9ydGFsaXR5Ij0iTU0gbGVzcyBmaXQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNTSBsb3dlciBmZXJ0aWxpdHkiPSJNTSBsZXNzIGZpdCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1NIGxvd2VyIG1vcnRhbGl0eSI9Ik1NIG1vcmUgZml0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTU4gaGlnaGVyIG1vcnRhbGl0eSI9Ik1OIGxlc3MgZml0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTU4gbG93ZXIgZmVydGlsaXR5Ij0iTU4gbGVzcyBmaXQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNTiBsb3dlciBtb3J0YWxpdHkiPSJNTiBtb3JlIGZpdCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5OIGhpZ2hlciBtb3J0YWxpdHkiPSJOTiBsZXNzIGZpdCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5OIGxvd2VyIGZlcnRpbGl0eSI9Ik5OIGxlc3MgZml0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTk4gbG93ZXIgbW9ydGFsaXR5Ij0iTk4gbW9yZSBmaXQiKSwKICAgICAgICAgZml0bmVzcy5hZ2dyZWdhdGVkID0gZmFjdG9yKGZpdG5lc3MuYWdncmVnYXRlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZXF1YWwgZml0bmVzcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTU0gbGVzcyBmaXQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1NIG1vcmUgZml0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNTiBsZXNzIGZpdCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTU4gbW9yZSBmaXQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5OIGxlc3MgZml0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOTiBtb3JlIGZpdCIpKSkgJT4lIAogIGdncGxvdChhZXMoeD1waGVub3R5cGUsIHk9cG9wdWxhdGlvbikpICsgCiAgZ2VvbV9ib3hwbG90KGZpbGw9ImdyZXkiKSArIAogIGZhY2V0X2dyaWQoZml0bmVzcy5hZ2dyZWdhdGVkfmZhY3Rvcihob21lLnJhbmdlLnJhZGl1cyksIHNjYWxlcz0iZnJlZV95IikgKyAKICBsYWJzKHg9ImFnZW50IHBoZW5vdHlwZSIsIHk9InBvcHVsYXRpb24gYXQgZW5kIG9mIHNpbXVsYXRpb24iKSArIAogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE2KQpgYGAKCiMjIyBGaWd1cmUgNDogRXhhbXBsZSBNb2RlbCBUcmFqZWN0b3J5IHdpdGggTG9naXN0aWNhbCBGb3JhZ2luZyAoRm9yYWdpbmcgUmFkaXVzPTEyKQoKYGBge3IgZWNobz1ULCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NX0KSG9taW5pbl9kZW1vZ3JhcGh5X3RyYWplY3RvcnkgJT4lIAogIGdncGxvdChhZXMoeT1wb3B1bGF0aW9uLCB4PXN0ZXApKSArIAogIGdlb21fbGluZShhZXMoY29sb3I9cGhlbm90eXBlKSwgc2l6ZT0yKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsICJvcmFuZ2UiLCAiZ3JleSIsICJmb3Jlc3RncmVlbiIsICJibHVlIikpICsgCiAgbGFicyh4PSJtb2RlbCBzdGVwIiwgeT0icG9wdWxhdGlvbiIsIGNvbG9yPSJhZ2VudCBwaGVub3R5cGUiKSArIAogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE2KSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikKYGBgCgojIyBEZW1vZ3JhcGhpYyBEeW5hbWljcyBvZiBXZXN0IE1lZGl0ZXJyYW5lYW4KCgojIyMgRmlndXJlIDVhOiBTdW1tZWQgUHJvYmFiaWxpdHkgRGlzdHJpYnV0aW9uIChTUEQpIG9mIFJhZGlvY2FyYm9uIERhdGVzIGluIHRoZSBXZXN0IE1lZGl0ZXJyYW5lYW4KCiMjIyMgQ2FsaWJyYXRlIGRhdGVzCgpgYGB7ciBjYWxpYnJhdGUgZGF0ZXMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VCwgcmVzdWx0cz0iaGlkZSJ9CmMxNGRhdGVzJEJQLmNhbC5tZWRpYW4gPC0gYzE0ZGF0ZXMgJT4lIAogIHdpdGgoLiwgY2FsaWJyYXRlKHg9QzE0Lm1lYW4sIGVycm9ycz1DMTQuU0QsIGNhbEN1cnZlcyA9IGNhbGliLmN1cnZlLCBub3JtYWxpc2VkPVRSVUUsIGNhbE1hdHJpeD1GQUxTRSkpICU+JSAKICBtZWRDYWwoKQpgYGAKCgojIyMjIENhbGN1bGF0ZSBTUEQgZm9yIGVudGlyZSByZWdpb24KRGF0ZXMgZmlsZSBmaWx0ZXJlZCB0byByZW1vdmUgYWxsIGRhdGUgd2l0aCBDT1YgPiAwLjEKCmBgYHtyIFNQRC1hbGwsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIHJlc3VsdHM9ImhpZGUifQpkYXRlLmJpbnMgPC0gYzE0ZGF0ZXMgJT4lIAogIGRwbHlyOjpmaWx0ZXIoY2FsaWIuY3VydmUgIT0gIm5vcm1hbCIpICU+JSAgCiAgd2l0aCguLCBiaW5QcmVwKHNpdGUsIEMxNC5tZWFuLCAyMDApKQoKbW9kZWwuYWxsIDwtIGMxNGRhdGVzICU+JSAKICBkcGx5cjo6ZmlsdGVyKGNhbGliLmN1cnZlICE9ICJub3JtYWwiKSAlPiUgIAogIHdpdGgoLiwgY2FsaWJyYXRlKHg9QzE0Lm1lYW4sIAogICAgICAgICAgICAgICAgICAgIGVycm9ycz1DMTQuU0QsIAogICAgICAgICAgICAgICAgICAgIGNhbEN1cnZlcyA9IGNhbGliLmN1cnZlLCAKICAgICAgICAgICAgICAgICAgICBub3JtYWxpc2VkPVRSVUUsIAogICAgICAgICAgICAgICAgICAgIGNhbE1hdHJpeD1GQUxTRSkpICU+JSAKICBtb2RlbFRlc3QoLiwgdGltZVJhbmdlID0gYyg0MDAwMCw3MDAwKSwgCiAgICAgICAgICAgIGVycm9ycyA9IGMxNGRhdGVzJEMxNC5TRCwgCiAgICAgICAgICAgIHJ1bm0gPSA1MDAsIAogICAgICAgICAgICBtb2RlbD0iZXhwb25lbnRpYWwiLCAKICAgICAgICAgICAgbnNpbSA9IDIwMCwgCiAgICAgICAgICAgIG5jb3JlcyA9IG5jb3JlcywKICAgICAgICAgICAgbWV0aG9kID0gJ2NhbHNhbXBsZScsIAogICAgICAgICAgICBiaW5zID0gZGF0ZS5iaW5zKQpgYGAKCgojIyMjIEdyYXBoIFNQRAoKYGBge3IgU1BELWFsbCBncmFwaCwgZmlnLmhlaWdodD00LjU1LCBmaWcud2lkdGg9MTIsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89VCwgcmVzdWx0cz0iaGlkZSJ9CnBhcihtYXI9Yyg3LDEwLDcsMykpCnBsb3QobW9kZWwuYWxsLCB4bGltID0gYygzNTAwMCw4MDAwKSwgY29sLm9icyA9ICdyZWQnLCBsd2Qub2JzID0gMywgZHJhd2F4ZXMgPSBGKQpheGlzKDEsIGNleC5heGlzID0gMSwgcG9zID0gLS4wMDA2KQpheGlzKDIsIGNleC5heGlzID0gMSwgcG9zID0gMzU1MDApCm10ZXh0KHNpZGU9MSwgbGluZT0zLCAieWVhcnMgY2FsIEJQIiwgY2V4PTEuMykKbXRleHQoc2lkZT0yLCBsaW5lPTQsICJzdW1tZWQgcHJvYmFiaWxpdHkiLCBjZXg9MS4zKQp0aXRsZShtYWluPXBhc3RlKCJXZXN0IE1lZGl0ZXJyYW5lYW4gTGF0ZSBQbGVpc3RvY2VuZSBBc3NlbWJsYWdlcyAoTiA9ICIsIG5yb3coc3Vic2V0KGMxNGRhdGVzLCBjYWxpYi5jdXJ2ZSAhPSAibm9ybWFsIikpLCAiKSIpLCBjZXgubWFpbiA9IDEuNSkKYGBgCgoKCiMjIyBGaWd1cmUgNWI6IFNQRCBQZXJtdXRhdGlvbiBUZXN0IG9mIEFnZ3JlZ2F0ZWQgVGVjaG5vY29tcGxleGVzCgojIyMjIENsYXNzaWZ5IGFnZ3JlZ2F0ZWQgdGVjaG5vY29tcGxleGVzCgpgYGB7ciBjbGFzc2lmaXkgdGVjaG5vY29tcGxleGVzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPVQsIHJlc3VsdHM9J2hpZGUnfQpjMTRkYXRlcyA8LSBjMTRkYXRlcyAlPiUgCiAgbXV0YXRlKGluZHVzdHJ5Lmdyb3VwID0gCiAgICAgICAgICAgY2FzZV93aGVuKAogICAgICAgICAgICAgc3RyX2RldGVjdCh0b2xvd2VyKGluZHVzdHJ5KSwgImF1cmlnIikgfiAiQXVyaWduYWNpYW4iLCAKICAgICAgICAgICAgIHN0cl9kZXRlY3QodG9sb3dlcihpbmR1c3RyeSksICJnZHJhdiIpIH4gIkdyYXZldHRpYW4iLCAgCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KHRvbG93ZXIoaW5kdXN0cnkpLCAic29sdXQiKSB+ICJTb2x1dHJlYW4iLAogICAgICAgICAgICAgc3RyX2RldGVjdCh0b2xvd2VyKGluZHVzdHJ5KSwgIm1pZGRsZSBzb2x1dHJlYW4iKSB+ICJTb2x1dHJlYW4iLCAKICAgICAgICAgICAgIHN0cl9kZXRlY3QodG9sb3dlcihpbmR1c3RyeSksICJzYWxwIikgfiAiU29sdXRyZWFuIiwgICAgICAgICAgICAgIAogICAgICAgICAgICAgc3RyX2RldGVjdCh0b2xvd2VyKGluZHVzdHJ5KSwgImVwaWciKSB+ICJNYWdkYWxlbmlhbiIsICAKICAgICAgICAgICAgIHN0cl9kZXRlY3QodG9sb3dlcihpbmR1c3RyeSksICJlcGktZ3IiKSB+ICJNYWdkYWxlbmlhbiIsCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KHRvbG93ZXIoaW5kdXN0cnkpLCAiZXBwaWciKSB+ICJNYWdkYWxlbmlhbiIsCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KHRvbG93ZXIoaW5kdXN0cnkpLCAiZXBwZ3IiKSB+ICJNYWdkYWxlbmlhbiIsCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KHRvbG93ZXIoaW5kdXN0cnkpLCAiYXBpZyIpIH4gIk1hZ2RhbGVuaWFuIiwKICAgICAgICAgICAgIHN0cl9kZXRlY3QodG9sb3dlcihpbmR1c3RyeSksICJtYWdkIikgfiAiTWFnZGFsZW5pYW4iLAogICAgICAgICAgICAgc3RyX2RldGVjdCh0b2xvd2VyKGluZHVzdHJ5KSwgImJhZGVnIikgfiAiTWFnZGFsZW5pYW4iLAogICAgICAgICAgICAgc3RyX2RldGVjdCh0b2xvd2VyKGluZHVzdHJ5KSwgImdyYXZldCIpIH4gIkdyYXZldHRpYW4iLCAgCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KHRvbG93ZXIoaW5kdXN0cnkpLCAiZ3JhdnQiKSB+ICJHcmF2ZXR0aWFuIiwgIAogICAgICAgICAgICAgc3RyX2RldGVjdCh0b2xvd2VyKGluZHVzdHJ5KSwgImF6aWwiKSB+ICJFcGlwYWxlb2xpdGhpYyIsIAogICAgICAgICAgICAgc3RyX2RldGVjdCh0b2xvd2VyKGluZHVzdHJ5KSwgInJvbWFuZWxsIikgfiAiRXBpcGFsZW9saXRoaWMiLCAKICAgICAgICAgICAgIHN0cl9kZXRlY3QodG9sb3dlcihpbmR1c3RyeSksICJlcGlwYWwiKSB+ICJFcGlwYWxlb2xpdGhpYyIsIAogICAgICAgICAgICAgc3RyX2RldGVjdCh0b2xvd2VyKGluZHVzdHJ5KSwgIm1lc29sIikgfiAiTWVzb2xpdGhpYyIsIAogICAgICAgICAgICAgc3RyX2RldGVjdCh0b2xvd2VyKGluZHVzdHJ5KSwgInNhdXZlIikgfiAiTWVzb2xpdGhpYyIsIAogICAgICAgICAgICAgc3RyX2RldGVjdCh0b2xvd2VyKGluZHVzdHJ5KSwgInRhcmRlbiIpIH4gIk1lc29saXRoaWMiLCAKICAgICAgICAgICAgIHN0cl9kZXRlY3QodG9sb3dlcihpbmR1c3RyeSksICJtb250Y2wiKSB+ICJNZXNvbGl0aGljIiwgCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KHRvbG93ZXIoaW5kdXN0cnkpLCAibW9udGFkIikgfiAiTWVzb2xpdGhpYyIsIAogICAgICAgICAgICAgc3RyX2RldGVjdCh0b2xvd2VyKGluZHVzdHJ5KSwgImNhc3RlbCIpIH4gIk1lc29saXRoaWMiCiAgICAgICAgICAgICApLCAKICAgICAgICAgaW5kdXN0cnkuZ3JvdXAgPSBmYWN0b3IoaW5kdXN0cnkuZ3JvdXAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJBdXJpZ25hY2lhbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcmF2ZXR0aWFuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNvbHV0cmVhbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNYWdkYWxlbmlhbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFcGlwYWxlb2xpdGhpYyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNZXNvbGl0aGljIikpLAogICAgICAgICAuYWZ0ZXI9aW5kdXN0cnkpCmBgYAoKCgojIyMjIFBlcm11dGF0aW9uIHRlc3Qgb2YgYWdncmVnYXRlZCB0ZWNobm9jb21wbGV4ZXMKCmBgYHtyIFNQRC1wZXJtLWluZHVzdHJpZXMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpjMTRkYXRlcy5pbmR1c3RyeS5ncm91cCA8LSBjMTRkYXRlcyAlPiUgCiAgZHBseXI6OmZpbHRlcighaXMubmEoaW5kdXN0cnkuZ3JvdXApICYgY2FsaWIuY3VydmUgIT0gIm5vcm1hbCIpCgpjMTRkYXRlcy5pbmR1c3RyeS5ncm91cCA8LSBjMTRkYXRlcy5pbmR1c3RyeS5ncm91cFtvcmRlcihjMTRkYXRlcy5pbmR1c3RyeS5ncm91cCRpbmR1c3RyeS5ncm91cCksIF0KCmRhdGUuYmlucyA8LSAgYzE0ZGF0ZXMuaW5kdXN0cnkuZ3JvdXAgJT4lIAogIHdpdGgoLiwgYmluUHJlcChzaXRlLCBDMTQubWVhbiwgMjAwKSkKCnBlcm0udGVzdCA8LSBjMTRkYXRlcy5pbmR1c3RyeS5ncm91cCAlPiUgCiAgd2l0aCguLCBjYWxpYnJhdGUoeD1DMTQubWVhbiwgZXJyb3JzPUMxNC5TRCwgY2FsQ3VydmVzID0gY2FsaWIuY3VydmUsIG5vcm1hbGlzZWQ9VFJVRSwgY2FsTWF0cml4PUZBTFNFKSkgJT4lIAogIHBlcm1UZXN0KHRpbWVSYW5nZT1jKDQwMDAwLDcwMDApLCAKICAgICAgICAgICBiaW5zPWRhdGUuYmlucywKICAgICAgICAgICBtYXJrcz1jMTRkYXRlcy5pbmR1c3RyeS5ncm91cCRpbmR1c3RyeS5ncm91cCwgCiAgICAgICAgICAgbnNpbSA9IDIwMCwgCiAgICAgICAgICAgcnVubSA9IDUwMCwgCiAgICAgICAgICAgZGF0ZW5vcm1hbGlzZWQ9VFJVRSkKYGBgCgojIyMjIFBlcm11dGF0aW9uIHRlc3QgcmVzdWx0cwpgYGB7ciBTUEQtcGVybS1pbmR1c3RyaWVzLXJlc3VsdHMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnN1bW1hcnkocGVybS50ZXN0KQpgYGAKCgojIyMjIEdyYXBoIFBlcm11dGF0aW9ucwoKYGBge3IgU1BELXBlcm0taW5kdXN0cmllcyBncmFwaCwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTMsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0naGlkZScsIG1lc3NhZ2U9RkFMU0V9CnBsb3QocGVybS50ZXN0LCAKICAgICBmb2NhbG0gPSAiQXVyaWduYWNpYW4iLCAKICAgICB4bGltID0gYygzNTAwMCw4MDAwKSwgCiAgICAgY29sLm9icyA9ICdyZWQnLCAKICAgICBsd2Qub2JzID0gMywKICAgICBiYnR5ID0gJ2InLCAKICAgICB5bGltID0gYygwLCAwLjA0KSwKICAgICBkcmF3YXhlcyA9IEYpCiAgYXhpcygxLCBjZXguYXhpcyA9IDEsIHBvcyA9IC0uMDAwNikKICBheGlzKDIsIGNleC5heGlzID0gMSwgcG9zID0gMzU1MDApCiAgbXRleHQoc2lkZT0xLCBsaW5lPTMsICJ5ZWFycyBjYWwgQlAiLCBjZXg9MS4zKQogIG10ZXh0KHNpZGU9MiwgbGluZT00LCAic3VtbWVkIHByb2JhYmlsaXR5IiwgY2V4PTEuMykKICB0aXRsZShtYWluPXBhc3RlKCJBdXJpZ25hY2lhbiAoTiA9ICIsIG5yb3coc3Vic2V0KGMxNGRhdGVzLCBpbmR1c3RyeS5ncm91cCA9PSAiQXVyaWduYWNpYW4iKSksICIpIiksIGNleC5tYWluID0gMS41KQogCnBsb3QocGVybS50ZXN0LCAKICAgICBmb2NhbG0gPSAiR3JhdmV0dGlhbiIsIAogICAgIHhsaW0gPSBjKDM1MDAwLDgwMDApLCAKICAgICBjb2wub2JzID0gJ3JlZCcsIAogICAgIGx3ZC5vYnMgPSAzLAogICAgIGJidHkgPSAnYicsIAogICAgIHlsaW0gPSBjKDAsIDAuMDQpLAogICAgIGRyYXdheGVzID0gRikKICBheGlzKDEsIGNleC5heGlzID0gMSwgcG9zID0gLS4wMDA2KQogIGF4aXMoMiwgY2V4LmF4aXMgPSAxLCBwb3MgPSAzNTUwMCkKICBtdGV4dChzaWRlPTEsIGxpbmU9MywgInllYXJzIGNhbCBCUCIsIGNleD0xLjMpCiAgbXRleHQoc2lkZT0yLCBsaW5lPTQsICJzdW1tZWQgcHJvYmFiaWxpdHkiLCBjZXg9MS4zKQogIHRpdGxlKG1haW49cGFzdGUoIkdyYXZldHRpYW4gKE4gPSAiLCBucm93KHN1YnNldChjMTRkYXRlcywgaW5kdXN0cnkuZ3JvdXAgPT0gIkdyYXZldHRpYW4iKSksICIpIiksIGNleC5tYWluID0gMS41KQogIApwbG90KHBlcm0udGVzdCwgCiAgICAgZm9jYWxtID0gIlNvbHV0cmVhbiIsIAogICAgIHhsaW0gPSBjKDM1MDAwLDgwMDApLCAKICAgICBjb2wub2JzID0gJ3JlZCcsIAogICAgIGx3ZC5vYnMgPSAzLAogICAgIGJidHkgPSAnYicsIAogICAgIHlsaW0gPSBjKDAsIDAuMDQpLAogICAgIGRyYXdheGVzID0gRikKICBheGlzKDEsIGNleC5heGlzID0gMSwgcG9zID0gLS4wMDA2KQogIGF4aXMoMiwgY2V4LmF4aXMgPSAxLCBwb3MgPSAzNTUwMCkKICBtdGV4dChzaWRlPTEsIGxpbmU9MywgInllYXJzIGNhbCBCUCIsIGNleD0xLjMpCiAgbXRleHQoc2lkZT0yLCBsaW5lPTQsICJzdW1tZWQgcHJvYmFiaWxpdHkiLCBjZXg9MS4zKQogIHRpdGxlKG1haW49cGFzdGUoIlNvbHV0cmVhbiAoTiA9ICIsIG5yb3coc3Vic2V0KGMxNGRhdGVzLCBpbmR1c3RyeS5ncm91cCA9PSAiU29sdXRyZWFuIikpLCAiKSIpLCBjZXgubWFpbiA9IDEuNSkKICAKcGxvdChwZXJtLnRlc3QsIAogICAgIGZvY2FsbSA9ICJNYWdkYWxlbmlhbiIsIAogICAgIHhsaW0gPSBjKDM1MDAwLDgwMDApLCAKICAgICBjb2wub2JzID0gJ3JlZCcsIAogICAgIGx3ZC5vYnMgPSAzLAogICAgIGJidHkgPSAnYicsIAogICAgIHlsaW0gPSBjKDAsIDAuMSksCiAgICAgZHJhd2F4ZXMgPSBGKQogIGF4aXMoMSwgY2V4LmF4aXMgPSAxLCBwb3MgPSAtLjAwMDYpCiAgYXhpcygyLCBjZXguYXhpcyA9IDEsIHBvcyA9IDM1NTAwKQogIG10ZXh0KHNpZGU9MSwgbGluZT0zLCAieWVhcnMgY2FsIEJQIiwgY2V4PTEuMykKICBtdGV4dChzaWRlPTIsIGxpbmU9NCwgInN1bW1lZCBwcm9iYWJpbGl0eSIsIGNleD0xLjMpCiAgdGl0bGUobWFpbj1wYXN0ZSgiTWFnZGFsZW5pYW4gKE4gPSAiLCBucm93KHN1YnNldChjMTRkYXRlcywgaW5kdXN0cnkuZ3JvdXAgPT0gIk1hZ2RhbGVuaWFuIikpLCAiKSIpLCBjZXgubWFpbiA9IDEuNSkKICAKcGxvdChwZXJtLnRlc3QsIAogICAgIGZvY2FsbSA9ICJFcGlwYWxlb2xpdGhpYyIsIAogICAgIHhsaW0gPSBjKDM1MDAwLDgwMDApLCAKICAgICBjb2wub2JzID0gJ3JlZCcsIAogICAgIGx3ZC5vYnMgPSAzLAogICAgIGJidHkgPSAnYicsIAogICAgIHlsaW0gPSBjKDAsIDAuMDQpLAogICAgIGRyYXdheGVzID0gRikKICBheGlzKDEsIGNleC5heGlzID0gMSwgcG9zID0gLS4wMDA2KQogIGF4aXMoMiwgY2V4LmF4aXMgPSAxLCBwb3MgPSAzNTUwMCkKICBtdGV4dChzaWRlPTEsIGxpbmU9MywgInllYXJzIGNhbCBCUCIsIGNleD0xLjMpCiAgbXRleHQoc2lkZT0yLCBsaW5lPTQsICJzdW1tZWQgcHJvYmFiaWxpdHkiLCBjZXg9MS4zKQogIHRpdGxlKG1haW49cGFzdGUoIkVwaXBhbGVvbGl0aGljIChOID0gIiwgbnJvdyhzdWJzZXQoYzE0ZGF0ZXMsIGluZHVzdHJ5Lmdyb3VwID09ICJFcGlwYWxlb2xpdGhpYyIpKSwgIikiKSwgY2V4Lm1haW4gPSAxLjUpCiAgCnBsb3QocGVybS50ZXN0LCAKICAgICBmb2NhbG0gPSAiTWVzb2xpdGhpYyIsIAogICAgIHhsaW0gPSBjKDM1MDAwLDgwMDApLCAKICAgICBjb2wub2JzID0gJ3JlZCcsIAogICAgIGx3ZC5vYnMgPSAzLAogICAgIGJidHkgPSAnYicsIAogICAgIHlsaW0gPSBjKDAsIDAuMTIpLCAKICAgICBkcmF3YXhlcyA9IEYpCiAgYXhpcygxLCBjZXguYXhpcyA9IDEsIHBvcyA9IC0uMDAwNikKICBheGlzKDIsIGNleC5heGlzID0gMSwgcG9zID0gMzU1MDApCiAgbXRleHQoc2lkZT0xLCBsaW5lPTMsICJ5ZWFycyBjYWwgQlAiLCBjZXg9MS4zKQogIG10ZXh0KHNpZGU9MiwgbGluZT00LCAic3VtbWVkIHByb2JhYmlsaXR5IiwgY2V4PTEuMykKICB0aXRsZShtYWluPXBhc3RlKCJNZXNvbGl0aGljIChOID0gIiwgbnJvdyhzdWJzZXQoYzE0ZGF0ZXMsIGluZHVzdHJ5Lmdyb3VwID09ICJNZXNvbGl0aGljIikpLCAiKSIpLCBjZXgubWFpbiA9IDEuNSkKYGBgCgo=